
#----------------------------------------------------------------------------------------------------------------
# DWDataReader example for Python
#----------------------------------------------------------------------------------------------------------------
# Author: Dewesoft
# Notes:
#   - requires DWDataReaderLib.dll 4.0.0.0 or later
#   - tested with Python 3.4
#----------------------------------------------------------------------------------------------------------------

from .DWDataReaderHeader import *
from ctypes import *
import _ctypes


def get_dxd_data_sample():
    lib = cdll.LoadLibrary('DWDataReader/DWDataReaderLib64.dll')

    # init data reader
    if lib.DWInit() != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWInit() failed")

    # get data reader version
    print("DWDataReader version: " + str(lib.DWGetVersion()))

    # add additional data reader
    if lib.DWAddReader() != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWAddReader() failed")

    # get number of open data readers
    num = c_int()
    if lib.DWGetNumReaders(byref(num)) != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWGetNumReaders() failed")
    print("Number of data readers: " + str(num.value))

    # open data file
    # data file must be in the same folder as the python script
    # str1 = "C:\\Users\\14732\\Desktop\\测试\\dxd数据\\Test_2024_08_21_095324.dxd"
    str1 = "./Test_2024_08_21_095324.dxd"
    file_name = c_char_p(str1.encode())
    file_info = DWFileInfo(0, 0, 0)
    if lib.DWOpenDataFile(file_name, c_void_p(addressof(file_info))) != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWOpenDataFile() failed")

    measurement_info = DWMeasurementInfo(0, 0, 0, 0)

    if lib.DWGetMeasurementInfo(c_void_p(addressof(measurement_info))) != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWGetMeasurementInfo() failed")

    print("Sample rate: %.2f" % measurement_info.sample_rate)
    print("Start measure time: %.2f" % measurement_info.start_measure_time)
    print("Start store time: %.2f" % measurement_info.start_store_time)
    print("Duration: %.2f" % measurement_info.duration)

    # export XML
    str2 = 'SetupFile.xml'
    file_name = c_char_p(str2.encode())
    if lib.DWExportHeader(file_name) != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWExportHeader() failed")

    # get num channels
    num = lib.DWGetChannelListCount()
    if num == -1:
        DWRaiseError("DWDataReader: DWGetChannelListCount() failed")
    print("Number of channels: %d" % num)

    # get channel list
    ch_list = (DWChannel * num)()
    if lib.DWGetChannelList(byref(ch_list)) != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWGetChannelList() failed")

    print("\n")

    # ----------------------------------------------------------------------------------------------------------------
    # channel loop
    # ----------------------------------------------------------------------------------------------------------------
    all_channels_data = {}  # 初始化一个列表来保存所有通道的数据
    for i in range(0, num):
        # basic channel properties
        print("************************************************")
        print("Channel #%d" % i)
        print("************************************************")
        print("Index: %d" % ch_list[i].index)
        print("Name: %s" % ch_list[i].name.decode())
        print("Unit: %s" % ch_list[i].unit.decode())
        print("Description: %s" % ch_list[i].description.decode())

        # channel factors
        idx = c_int(ch_list[i].index)
        ch_scale = c_double()
        ch_offset = c_double()
        if lib.DWGetChannelFactors(idx, byref(ch_scale), byref(ch_offset)) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetChannelFactors() failed")

        print("Scale: %.2f" % ch_scale.value)
        print("Offset: %.2f" % ch_offset.value)

        # channel type
        max_len = c_int(INT_SIZE)
        buff = create_string_buffer(max_len.value)
        p_buff = cast(buff, POINTER(c_void_p))
        if lib.DWGetChannelProps(idx, c_int(DWChannelProps.DW_CH_TYPE.value), p_buff,
                                 byref(max_len)) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetChannelProps() failed")
        ch_type = cast(p_buff, POINTER(c_int)).contents

        if ch_type.value == DWChannelType.DW_CH_TYPE_SYNC.value:
            print("Channel type: sync")
        elif ch_type.value == DWChannelType.DW_CH_TYPE_ASYNC.value:
            print("Channel type: async")
        elif ch_type.value == DWChannelType.DW_CH_TYPE_SV.value:
            print("Channel type: single value")
        else:
            print("Channel type: unknown")

        # channel data type
        if lib.DWGetChannelProps(idx, c_int(DWChannelProps.DW_DATA_TYPE.value), p_buff,
                                 byref(max_len)) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetChannelProps() failed")
        data_type = cast(p_buff, POINTER(c_int)).contents
        print("Data type: %s" % DWDataType(data_type.value).name)

        # channel long name length
        channel_long_name_len_buff = create_string_buffer(INT_SIZE)
        if lib.DWGetChannelProps(idx, c_int(DWChannelProps.DW_CH_LONGNAME_LEN.value), channel_long_name_len_buff,
                                 byref(max_len)) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetChannelProps() failed")
        long_name_len = cast(channel_long_name_len_buff, POINTER(c_int)).contents

        # channel long name
        channel_long_name_buff = create_string_buffer(long_name_len.value)
        if lib.DWGetChannelProps(idx, c_int(DWChannelProps.DW_CH_LONGNAME.value), channel_long_name_buff,
                                 byref(long_name_len)) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetChannelProps() failed")
        print("Long name : %s" % channel_long_name_buff.value.decode())

        # channel xml length
        channel_xml_len_buff = create_string_buffer(INT_SIZE)
        if lib.DWGetChannelProps(idx, c_int(DWChannelProps.DW_CH_XML_LEN.value), channel_xml_len_buff,
                                 byref(max_len)) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetChannelProps() failed")
        xml_len = cast(channel_xml_len_buff, POINTER(c_int)).contents

        # channel xml
        channel_xml_buff = create_string_buffer(xml_len.value)
        if lib.DWGetChannelProps(idx, c_int(DWChannelProps.DW_CH_XML.value), channel_xml_buff,
                                 byref(xml_len)) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetChannelProps() failed")
        print("Xml : %s" % channel_xml_buff.value.decode())

        # number of samples
        dw_ch_index = c_int(ch_list[i].index)
        sample_cnt = c_int()
        sample_cnt = lib.DWGetScaledSamplesCount(dw_ch_index)
        if sample_cnt < 0:
            DWRaiseError("DWDataReader: DWGetScaledSamplesCount() failed")
        print("Num. samples: %d" % sample_cnt)

        # get actual data
        data = create_string_buffer(
            DOUBLE_SIZE * sample_cnt * ch_list[i].array_size)
        time_stamp = create_string_buffer(DOUBLE_SIZE * sample_cnt)
        p_data = cast(data, POINTER(c_double))
        p_time_stamp = cast(time_stamp, POINTER(c_double))
        if lib.DWGetScaledSamples(dw_ch_index, c_int64(0), sample_cnt, p_data,
                                  p_time_stamp) != DWStatus.DWSTAT_OK.value:
            DWRaiseError("DWDataReader: DWGetScaledSamples() failed")

        channel_samples = []  # 创建一个字典列表来保存当前通道的数据
        # diplay data
        for j in range(0, sample_cnt):
            for k in range(0, ch_list[i].array_size):
                # 将时间和值作为字典添加到列表中
                channel_samples.append({
                    "Time": p_time_stamp[j],
                    "Value": p_data[j * ch_list[i].array_size + k]
                })
        # 将通道名称和其对应的数据列表添加到channel_data中
        channel_name = str(ch_list[i].name.decode())
        # 将该通道的数据添加到all_channels_data中
        all_channels_data[channel_name] = channel_samples
    # ----------------------------------------------------------------------------------------------------------------
    # end channel loop
    # ----------------------------------------------------------------------------------------------------------------

    # close data file
    if lib.DWCloseDataFile() != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWCloseDataFile() failed")

    # deinit
    if lib.DWDeInit() != DWStatus.DWSTAT_OK.value:
        DWRaiseError("DWDataReader: DWDeInit() failed")

    # close DLL
    _ctypes.FreeLibrary(lib._handle)
    del lib
    return all_channels_data

